package cn.edu.xmu.javaee.productdemomybatis.controller;

import cn.edu.xmu.javaee.core.exception.BusinessException;
import cn.edu.xmu.javaee.core.model.ReturnNo;
import cn.edu.xmu.javaee.core.model.ReturnObject;
import cn.edu.xmu.javaee.core.model.UserToken;
import cn.edu.xmu.javaee.core.util.JacksonUtil;
import cn.edu.xmu.javaee.core.validation.NewGroup;
import cn.edu.xmu.javaee.core.validation.UpdateGroup;
import cn.edu.xmu.javaee.productdemomybatis.service.vo.ProductVo;
import cn.edu.xmu.javaee.productdemomybatis.service.vo.CustomerProductVo;
import cn.edu.xmu.javaee.productdemomybatis.controller.dto.ProductDto;
import cn.edu.xmu.javaee.productdemomybatis.dao.bo.Product;
import cn.edu.xmu.javaee.productdemomybatis.service.ProductService;
import cn.edu.xmu.javaee.productdemomybatis.util.CloneFactory;
import cn.edu.xmu.javaee.productdemomybatis.util.RequestVariables;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static cn.edu.xmu.javaee.productdemomybatis.util.Common.changeHttpStatus;
import static cn.edu.xmu.javaee.productdemomybatis.util.Common.getI18nMessage;


/**
 * 商品控制器
 * @author Ming Qiu
 */
@RestController /*Restful的Controller对象*/
@RequestMapping(value = "/shops/{shopId}", produces = "application/json;charset=UTF-8")
@Slf4j
@RequiredArgsConstructor
public class AdminProductController {

    private final ProductService productService;
    private final RequestVariables requestVariables;
    private final MessageSource messageSource;

    @PostMapping("/products")
    public ReturnObject createDraft(@PathVariable Integer shopId,
                                    @RequestBody @Validated(value = NewGroup.class) ProductDto dto, HttpServletRequest request, HttpServletResponse response) {
        MessageSourceAccessor messageSourceAccessor = new MessageSourceAccessor(this.messageSource, LocaleContextHolder.getLocale());
        log.debug("createDraft: dto = {}",dto);
        ReturnObject retObj = null;
        try{
            String authorization = request.getHeader("Authorization");
            if (Objects.nonNull(authorization)) {
                UserToken user = JacksonUtil.toObj(authorization, UserToken.class);
                this.requestVariables.setUser(user);
            }else{
                throw new BusinessException(ReturnNo.AUTH_NEED_LOGIN);
            }

            Product product = CloneFactory.copy(new Product(), dto);
            product.setShopId(shopId);
            ProductVo retProduct = this.productService.createProduct(product);
            retObj = new ReturnObject(ReturnNo.CREATED, messageSourceAccessor.getMessage(ReturnNo.CREATED.getMessage()), retProduct);
        }
        catch (BusinessException e){
            retObj = new ReturnObject(e.getErrno(), getI18nMessage(e,messageSourceAccessor));
        }
        changeHttpStatus(retObj.getCode(), response);
        return  retObj;
    }

    @GetMapping("/products/{id}")
    public ReturnObject getProductById(@PathVariable Integer shopId, @PathVariable("id") Integer id,HttpServletRequest request, HttpServletResponse response) {

        log.debug("getProductById: shopId = {}, id = {}",shopId, id);
        MessageSourceAccessor messageSourceAccessor = new MessageSourceAccessor(this.messageSource, LocaleContextHolder.getLocale());
        ReturnObject retObj = null;
        try {
            String authorization = request.getHeader("Authorization");
            if (Objects.nonNull(authorization)) {
                UserToken user = JacksonUtil.toObj(authorization, UserToken.class);
                this.requestVariables.setUser(user);
            }else{
                throw new BusinessException(ReturnNo.AUTH_NEED_LOGIN);
            }

            Product product = productService.retrieveSimpleProductByID(shopId, id);
            ProductVo productVo = CloneFactory.copy(new ProductVo(), product);
            retObj = new ReturnObject(ReturnNo.OK, messageSourceAccessor.getMessage(ReturnNo.OK.getMessage()), productVo);
        }
        catch (BusinessException e){
            retObj = new ReturnObject(e.getErrno(), getI18nMessage(e,messageSourceAccessor));
            changeHttpStatus(e.getErrno(), response);
        }
        return  retObj;
    }



    @GetMapping("/products")
    public ReturnObject searchProductByName(@PathVariable Integer shopId, @RequestParam String name, HttpServletRequest request, HttpServletResponse response) {
        MessageSourceAccessor messageSourceAccessor = new MessageSourceAccessor(this.messageSource, LocaleContextHolder.getLocale());
        ReturnObject retObj = null;
        try{
            String authorization = request.getHeader("Authorization");
            if (Objects.nonNull(authorization)) {
                UserToken user = JacksonUtil.toObj(authorization, UserToken.class);
                this.requestVariables.setUser(user);
            }else{
                throw new BusinessException(ReturnNo.AUTH_NEED_LOGIN);
            }

            List<ProductVo> data = this.productService.CustomerProductVo(shopId, name);
            retObj = new ReturnObject(ReturnNo.OK, messageSourceAccessor.getMessage(ReturnNo.OK.getMessage()), data);
        }
        catch (BusinessException e){
            retObj = new ReturnObject(e.getErrno(), getI18nMessage(e,messageSourceAccessor));
            changeHttpStatus(e.getErrno(), response);
        }
        return  retObj;
    }

    @PutMapping("/products/{id}")
    public ReturnObject modiProduct(@PathVariable Integer id, @RequestBody @Validated(UpdateGroup.class) ProductDto productDto, HttpServletRequest request, HttpServletResponse response){
        ReturnObject retObj = null;
        MessageSourceAccessor messageSourceAccessor = new MessageSourceAccessor(this.messageSource, LocaleContextHolder.getLocale());
        try{
            String authorization = request.getHeader("Authorization");
            if (Objects.nonNull(authorization)) {
                UserToken user = JacksonUtil.toObj(authorization, UserToken.class);
                this.requestVariables.setUser(user);
            }else{
                throw new BusinessException(ReturnNo.AUTH_NEED_LOGIN);
            }

            Product product = CloneFactory.copy(new Product(), productDto);;
            product.setId(id);
            productService.modifyProduct(product);
            retObj = new ReturnObject(ReturnNo.OK, messageSourceAccessor.getMessage(ReturnNo.OK.getMessage()));
        }
        catch (BusinessException e){
            retObj = new ReturnObject(e.getErrno(), getI18nMessage(e,messageSourceAccessor));
        }
        changeHttpStatus(retObj.getCode(), response);
        return  retObj;

    }

    @DeleteMapping("/products/{id}")
    public ReturnObject delProduct(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) {
        ReturnObject retObj = null;
        MessageSourceAccessor messageSourceAccessor = new MessageSourceAccessor(this.messageSource, LocaleContextHolder.getLocale());
        try{
            String authorization = request.getHeader("Authorization");
            if (Objects.nonNull(authorization)) {
                UserToken user = JacksonUtil.toObj(authorization, UserToken.class);
                this.requestVariables.setUser(user);
            }else{
                throw new BusinessException(ReturnNo.AUTH_NEED_LOGIN);
            }
            productService.deleteProduct(id);
            retObj = new ReturnObject(ReturnNo.OK, messageSourceAccessor.getMessage(ReturnNo.OK.getMessage()));
        }
        catch (BusinessException e){
            retObj = new ReturnObject(e.getErrno(), getI18nMessage(e,messageSourceAccessor));
        }
        changeHttpStatus(retObj.getCode(), response);
        return  retObj;
    }

}
